#include <iostream>
#include <vector>
#include <string>
#include <regex>
#include <clang-c/Index.h>

CXChildVisitResult callBackGetTypesVisitor(CXCursor cursor, CXCursor parent, CXClientData client_data)
{
	// auto* data = reinterpret_cast<GetTypesStruct*>(client_data);
    std::string* infoPtr = (std::string*)(client_data);
	// std::unique_ptr<TypeBase> type;
    CXCursorKind kind = clang_getCursorKind(cursor);

    // std::cout<<"kind="<<kind<<"\n";

			// type = std::make_unique<Class>(parser::GetClass(cursor));
    if(kind == CXCursor_EnumDecl)
    {
        std::cout<<"Enum"<<"\n";
    }
    else if(kind == CXCursor_ClassDecl)
    {
        std::cout<<"Class"<<"\n";
    }
    else if(kind == CXCursor_StructDecl)
    {
        std::cout<<"Struct"<<"\n";
    }
    else if(kind == CXCursor_FunctionDecl)
    {
        std::cout<<"Function"<<"\n";
    }
    else
    {
    }


	// const string& name = type->GetFullName();
	// if (type
			// && !name.empty()
			// && parser::IsRecursivelyPublic(cursor)
			// && !(name.back() == ':')
			// && regex_match(name, data->options->include)
			// && !regex_match(name, data->options->exclude))
	// {
		// data->types->push_back(std::move(type));
	// }

	return CXChildVisit_Recurse;
}

int main_tryClang(int argc, const char *argv[])//
{
    std::cout<<"ExeReflection: mainTryClang"<<"\n";

    std::string fileName = "data/clangTest/Node.hpp";
    
    CXIndex index = clang_createIndex(0, 0);
    
    //CXTranslationUnit unit = Parse(index, file, argc, argv);
    CXTranslationUnit unit = clang_parseTranslationUnit(
				index,
				fileName.c_str(), argv, argc,
				nullptr, 0,
				CXTranslationUnit_None);
	if (unit == nullptr)
	{
        std::cout << "Unable to parse translation unit. Quitting." << "\n";
		exit(-1);
	}
	
    unsigned diagnostics = clang_getNumDiagnostics(unit);

	if (diagnostics != 0)
	{
        std::cout << "> Diagnostics:" << "\n";
		for (int i = 0; i != diagnostics; ++i)
		{
			CXDiagnostic diag = clang_getDiagnostic(unit, i);
            CXString strDiag = clang_formatDiagnostic( diag, clang_defaultDiagnosticDisplayOptions());
            std::cout<< ">>> "<<(const char*)strDiag.data<<"\n";
		}
	}

    CXCursor cursor = clang_getTranslationUnitCursor(unit);

    //const Options& options)
	//vector<unique_ptr<TypeBase>> results;
	// struct GetTypesStruct
	// {
		// vector<unique_ptr<TypeBase>>* types;
		// const parser::Options* options;
	// };
	//GetTypesStruct data = { &results, &options };
    std::string infor;
	unsigned visitReturn = clang_visitChildren(cursor, callBackGetTypesVisitor, &infor);

    std::cout<<"visitReturn="<<visitReturn<<"\n";
    std::cout<<"Enum break="<<CXChildVisit_Break<<"\n";
    std::cout<<"Enum Continue="<<CXChildVisit_Continue<<"\n";
    std::cout<<"Enum Recurse="<<CXChildVisit_Recurse<<"\n";

    return 1;
}
